﻿/*
Xin YUAN, 2022, BSD (2)
*/

////////////////////////////////////////////////////////////////////////////////
#ifndef __CTL_IMAGE_HISTOGRAM_H__
#define __CTL_IMAGE_HISTOGRAM_H__
////////////////////////////////////////////////////////////////////////////////

#ifndef __CTL_IMAGE_DATA_H__
	#error histogram.h requires data.h to be included first.
#endif

////////////////////////////////////////////////////////////////////////////////
namespace CTL {
////////////////////////////////////////////////////////////////////////////////

//Gray --> Histogram

template <class TGrayData>
inline void CalcHistogram(const TGrayData& gData, uint32_t uBins,
				uintptr_t* pHistogram) noexcept
{
	assert( uBins > 0 && uBins <= 256 );
	assert( pHistogram != nullptr );

	const auto& dimSizes(gData.GetSize());

	if ( uBins == 1 ) {
		pHistogram[0] = dimSizes[0] * dimSizes[1];  //no check
		return ;
	}

	uint32_t uSpan = 255 / uBins;
	if ( uSpan == 0 )
		uSpan = 1;

	for ( uint32_t i = 0; i < uBins; i ++ )
		pHistogram[i] = 0;

	MdaView<2> view;
	auto& dimStarts(view.GetStarts());
	auto& dimSteps(view.GetSteps());
	auto& dimEnds(view.GetEnds());
	dimStarts[0] = dimStarts[1] = 0;
	dimSteps[0] = dimSteps[1] = 1;
	dimEnds = dimSizes;
	typename TGrayData::Iterator iter;
	gData.GetIterator(view, iter);

	for ( ; !iter.IsEnd(); iter.ToNext() ) {
		const auto& srcPixel(iter.V());
		uint32_t v = (uint32_t)srcPixel.g / uSpan;
		if ( v >= uBins )
			v = uBins - 1;
		pHistogram[v] = pHistogram[v] + 1;
	}
}

////////////////////////////////////////////////////////////////////////////////
}
////////////////////////////////////////////////////////////////////////////////
#endif
////////////////////////////////////////////////////////////////////////////////
